#!/bin/bash
source ~/.bashrc
# 使用哪套配置文件
profiles="dev"
hostname=$(hostname)

# 微服务名对应 datacenter-id 映射
declare -A DATACENTER_MAP=(
    ["gradle-center"]=1
    ["gradle-config"]=2
    ["gradle-auth"]=3
    ["gradle-admin"]=4
    ["gradle-gateway"]=5
    ["gradle-jp"]=6
)

# 用法提示信息
usage() {
    echo "Usage: $0 {start|stop|restart|status|monitor|stop_all|gc} [app1.jar app2.jar ...]"
    exit 1
}

# 检查命令行参数是否正确
if [[ $# -lt 1 ]]; then
    usage
fi

# 操作类型（start、stop、restart、status）
action=$1
shift

# 待操作的jar文件列表
apps=("$@")

# 设置默认的JVM参数
DEFAULT_JVM_OPTS="-Xms512m -Xmx512m -Djava.net.preferIPv4Stack=true -Dfile.encoding=UTF-8 \
-Dsnowflake.worker-id=1 -Dsnowflake.enabled=true -Dspring.profiles.active=$profiles \
-Deureka.instance.hostname=$hostname"

# ------------------ 启动应用程序 ------------------
start_app() {
    app=$1
    jvm_opts=$2

    if [[ ! -f "$app" ]]; then
        echo -e "\033[0;31mERROR: The file $app does not exist.\033[0m"
        return
    fi

    # 加载自定义JVM参数 e.g. service.conf
    jvm_file="${app%.*}.conf"
    if [ -f "${jvm_file}" ]; then
        jvm_opts="$DEFAULT_JVM_OPTS $(cat "${jvm_file}")"
    fi

    app_name=$(basename "$app")
    service_name="${app_name%%.jar}"  # 去掉 .jar

    # 根据映射表获取 datacenter-id，找不到则默认1
    DATACENTER_ID=${DATACENTER_MAP[$service_name]:-1}

    # 替换或追加 datacenter-id
    if [[ "$jvm_opts" == *"-Dsnowflake.datacenter-id="* ]]; then
        jvm_opts=$(echo "$jvm_opts" | sed -E "s/-Dsnowflake\.datacenter-id=[0-9]+/-Dsnowflake.datacenter-id=$DATACENTER_ID/")
    else
        jvm_opts="$jvm_opts -Dsnowflake.datacenter-id=$DATACENTER_ID"
    fi

    # OTEL Agent 参数
    OTEL_AGENT_OPTS="-javaagent:$OPEN_AGENT_PATH/opentelemetry-javaagent.jar \
-Dotel.exporter.otlp.endpoint=http://$COLLECTOR_HOST:4318 \
-Dotel.exporter.otlp.protocol=http/protobuf \
-Dotel.resource.attributes=service.name=$service_name"

    jvm_opts="$jvm_opts $OTEL_AGENT_OPTS"

    # 检查是否已运行
    ps_output=$(ps aux | grep "$app_name" | grep -v grep | grep -v "$0")
    if [[ -n "$ps_output" ]]; then
        echo -e "\033[0;33mWARNING: $app_name is already running.\033[0m"
        return
    fi

    # 启动应用程序
    nohup java $jvm_opts -jar "$app" > /dev/null 2>&1 &
    echo $! > "$app.pid"
    echo "$jvm_opts"
    echo "Started $app_name"
}

# ------------------ 停止应用程序 ------------------
stop_app() {
    app=$1

    if [[ ! -f "$app" ]]; then
        echo -e "\033[0;31mERROR: The file $app does not exist.\033[0m"
        return
    fi

    app_name=$(basename "$app")
    pid_file="${app}.pid"

    if [[ -f "$pid_file" ]]; then
        PID=$(cat "$pid_file")
        kill $PID || true
        sleep 5
        kill -9 $PID 2>/dev/null || true
        rm "$pid_file"
        echo "Stopped $app_name"
    else
        ps_output=$(ps aux | grep "$app_name" | grep -v grep | grep -v "$0")
        if [[ -z "$ps_output" ]]; then
            echo -e "\033[0;33mWARNING: $app_name is not running.\033[0m"
            return
        fi
        PID=$(echo "$ps_output" | awk '{print $2}')
        kill -9 $PID
        echo "Stopped $app_name"
    fi
}

# ------------------ 重启应用程序 ------------------
restart_app() {
    app=$1
    jvm_opts=$2

    stop_app "$app"
    sleep 1
    start_app "$app" "$jvm_opts"
}

# ------------------ 检查状态 ------------------
check_status() {
    [[ ${#apps[@]} -eq 0 ]] && apps=(*.jar)

    for app in "${apps[@]}"; do
        [[ ! -f "$app" ]] && { echo -e "\033[0;31mERROR: The file $app does not exist.\033[0m"; continue; }

        app_name=$(basename "$app")
        pid_file="${app}.pid"

        # pid 文件存在但进程不存在，删除
        [[ -f "$pid_file" ]] && { pid=$(cat "$pid_file"); ps_output=$(ps -up "$pid" | grep "$app_name"); [[ -z "$ps_output" ]] && rm "$pid_file"; }

        ps_output=$(ps aux | grep "$app_name" | grep -v grep | grep -v "$0")
        if [[ -z "$ps_output" ]]; then
            echo -e "\033[0;31m$app_name is not running.\033[0m"
        else
            pid=$(echo "$ps_output" | awk '{print $2}')
            echo -e "\033[0;32m$app_name is running (PID: $pid).\033[0m"
            [[ ! -f "$pid_file" ]] && echo "$pid" > "$pid_file"
        fi
    done
}

# ------------------ 监控并启动 ------------------
check_and_start() {
    [[ ${#apps[@]} -eq 0 ]] && apps=(*.jar)

    for app in "${apps[@]}"; do
        [[ ! -f "$app" ]] && { echo "ERROR: The file $app does not exist."; continue; }

        app_name=$(basename "$app")
        pid_file="${app}.pid"

        if [[ -f "$pid_file" ]]; then
            pid=$(cat "$pid_file")
            ps_output=$(ps -up "$pid" | grep "$app_name")
            [[ -z "$ps_output" ]] && { rm "$pid_file"; echo "Starting $app_name..."; start_app "$app" "$DEFAULT_JVM_OPTS"; }
        else
            echo "Starting $app_name..."
            start_app "$app" "$DEFAULT_JVM_OPTS"
        fi
    done
}

# ------------------ 停止全部应用 ------------------
check_and_stop() {
    [[ ${#apps[@]} -eq 0 ]] && apps=(*.jar)

    for app in "${apps[@]}"; do
        [[ ! -f "$app" ]] && { echo "ERROR: The file $app does not exist."; continue; }

        app_name=$(basename "$app")
        pid_file="${app}.pid"

        [[ -f "$pid_file" ]] && { pid=$(cat "$pid_file"); ps_output=$(ps -up "$pid" | grep "$app_name"); [[ -n "$ps_output" ]] && stop_app "$app"; }
    done
}

# ------------------ 执行GC ------------------
gc() {
    app=$1
    pid_file="${app}.pid"
    [[ -f "$pid_file" ]] && pid=$(cat "$pid_file") && jcmd "${pid}" GC.run
}

# ------------------ 执行操作 ------------------
case $action in
    start)
        for app in "${apps[@]}"; do start_app "$app" "$DEFAULT_JVM_OPTS"; done
        ;;
    stop)
        for app in "${apps[@]}"; do stop_app "$app"; done
        ;;
    restart)
        for app in "${apps[@]}"; do restart_app "$app" "$DEFAULT_JVM_OPTS"; done
        ;;
    status)
        check_status
        ;;
    monitor)
        check_and_start
        ;;
    stop_all)
        check_and_stop
        ;;
    gc)
        for app in "${apps[@]}"; do gc "$app"; done
        ;;
    *)
        usage
        ;;
esac

exit 0
